home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / Mesa-3.0 / SRC / LINES.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-07-08  |  41.9 KB  |  1,600 lines

  1. /* $Id: lines.c,v 3.12 1998/07/08 01:03:28 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: lines.c,v $
  26.  * Revision 3.12  1998/07/08 01:03:28  brianp
  27.  * removed some unused variables
  28.  *
  29.  * Revision 3.11  1998/06/18 02:38:45  brianp
  30.  * re-implemented INTERP_STUV code for textured lines
  31.  *
  32.  * Revision 3.10  1998/06/18 01:51:07  brianp
  33.  * more work on AA texture coordinate interpolation
  34.  *
  35.  * Revision 3.9  1998/06/17 04:08:38  brianp
  36.  * textured, AA lines didn't interpolate texture coords correctly
  37.  *
  38.  * Revision 3.8  1998/06/17 01:18:14  brianp
  39.  * textured, AA lines test was backward (Marten Stromberg)
  40.  *
  41.  * Revision 3.7  1998/06/17 01:15:10  brianp
  42.  * include assert.h
  43.  *
  44.  * Revision 3.6  1998/06/11 01:58:40  brianp
  45.  * separate textured and non-textured AA line functions
  46.  *
  47.  * Revision 3.5  1998/06/09 03:23:55  brianp
  48.  * implemented antialiased lines
  49.  *
  50.  * Revision 3.4  1998/06/07 22:18:52  brianp
  51.  * implemented GL_EXT_multitexture extension
  52.  *
  53.  * Revision 3.3  1998/04/13 23:30:08  brianp
  54.  * fixed PB overflow bug (Randy Frank)
  55.  *
  56.  * Revision 3.2  1998/03/27 04:17:52  brianp
  57.  * fixed G++ warnings
  58.  *
  59.  * Revision 3.1  1998/02/04 00:44:29  brianp
  60.  * fixed casts and conditional expression problems for Amiga StormC compiler
  61.  *
  62.  * Revision 3.0  1998/01/31 20:55:24  brianp
  63.  * initial rev
  64.  *
  65.  */
  66.  
  67.  
  68. #ifdef PC_HEADER
  69. #include "all.h"
  70. #else
  71. #include <assert.h>
  72. #include "context.h"
  73. #include "depth.h"
  74. #include "feedback.h"
  75. #include "lines.h"
  76. #include "macros.h"
  77. #include "pb.h"
  78. #include "texstate.h"
  79. #include "types.h"
  80. #include "vb.h"
  81. #endif
  82.  
  83.  
  84.  
  85. void gl_LineWidth( GLcontext *ctx, GLfloat width )
  86. {
  87.    if (width<=0.0) {
  88.       gl_error( ctx, GL_INVALID_VALUE, "glLineWidth" );
  89.       return;
  90.    }
  91.    if (INSIDE_BEGIN_END(ctx)) {
  92.       gl_error( ctx, GL_INVALID_OPERATION, "glLineWidth" );
  93.       return;
  94.    }
  95.    ctx->Line.Width = width;
  96.    ctx->NewState |= NEW_RASTER_OPS;
  97. }
  98.  
  99.  
  100.  
  101. void gl_LineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
  102. {
  103.    if (INSIDE_BEGIN_END(ctx)) {
  104.       gl_error( ctx, GL_INVALID_OPERATION, "glLineStipple" );
  105.       return;
  106.    }
  107.    ctx->Line.StippleFactor = CLAMP( factor, 1, 256 );
  108.    ctx->Line.StipplePattern = pattern;
  109.    ctx->NewState |= NEW_RASTER_OPS;
  110. }
  111.  
  112.  
  113.  
  114. /**********************************************************************/
  115. /*****                    Rasterization                           *****/
  116. /**********************************************************************/
  117.  
  118.  
  119. /*
  120.  * There are 4 pairs (RGBA, CI) of line drawing functions:
  121.  *   1. simple:  width=1 and no special rasterization functions (fastest)
  122.  *   2. flat:  width=1, non-stippled, flat-shaded, any raster operations
  123.  *   3. smooth:  width=1, non-stippled, smooth-shaded, any raster operations
  124.  *   4. general:  any other kind of line (slowest)
  125.  */
  126.  
  127.  
  128. /*
  129.  * All line drawing functions have the same arguments:
  130.  * v1, v2 - indexes of first and second endpoints into vertex buffer arrays
  131.  * pv     - provoking vertex: which vertex color/index to use for flat shading.
  132.  */
  133.  
  134.  
  135.  
  136. static void feedback_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
  137. {
  138.    struct vertex_buffer *VB = ctx->VB;
  139.    GLfloat x1, y1, z1, w1;
  140.    GLfloat x2, y2, z2, w2;
  141.    GLfloat tex1[4], tex2[4], invq;
  142.    GLuint texSet = ctx->Texture.CurrentTransformSet;
  143.  
  144.    x1 = VB->Win[v1][0];
  145.    y1 = VB->Win[v1][1];
  146.    z1 = VB->Win[v1][2] / DEPTH_SCALE;
  147.    w1 = VB->Clip[v1][3];
  148.  
  149.    x2 = VB->Win[v2][0];
  150.    y2 = VB->Win[v2][1];
  151.    z2 = VB->Win[v2][2] / DEPTH_SCALE;
  152.    w2 = VB->Clip[v2][3];
  153.  
  154.    invq = (VB->MultiTexCoord[texSet][v1][3]==0.0) ? 1.0 : (1.0F / VB->TexCoord[v1][3]);
  155.    tex1[0] = VB->MultiTexCoord[texSet][v1][0] * invq;
  156.    tex1[1] = VB->MultiTexCoord[texSet][v1][1] * invq;
  157.    tex1[2] = VB->MultiTexCoord[texSet][v1][2] * invq;
  158.    tex1[3] = VB->MultiTexCoord[texSet][v1][3];
  159.    invq = (VB->MultiTexCoord[texSet][v2][3]==0.0) ? 1.0 : (1.0F / VB->TexCoord[v2][3]);
  160.    tex2[0] = VB->MultiTexCoord[texSet][v2][0] * invq;
  161.    tex2[1] = VB->MultiTexCoord[texSet][v2][1] * invq;
  162.    tex2[2] = VB->MultiTexCoord[texSet][v2][2] * invq;
  163.    tex2[3] = VB->MultiTexCoord[texSet][v2][3];
  164.  
  165.    if (ctx->StippleCounter==0) {
  166.       FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_LINE_RESET_TOKEN );
  167.    }
  168.    else {
  169.       FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_LINE_TOKEN );
  170.    }
  171.  
  172.    {
  173.       GLfloat color[4];
  174.       /* convert color from integer to a float in [0,1] */
  175.       color[0] = (GLfloat) VB->Color[pv][0] * (1.0F / 255.0F);
  176.       color[1] = (GLfloat) VB->Color[pv][1] * (1.0F / 255.0F);
  177.       color[2] = (GLfloat) VB->Color[pv][2] * (1.0F / 255.0F);
  178.       color[3] = (GLfloat) VB->Color[pv][3] * (1.0F / 255.0F);
  179.       gl_feedback_vertex( ctx, x1,y1,z1,w1, color,
  180.                           (GLfloat) VB->Index[pv], tex1 );
  181.       gl_feedback_vertex( ctx, x2,y2,z2,w2, color,
  182.                           (GLfloat) VB->Index[pv], tex2 );
  183.    }
  184.  
  185.    ctx->StippleCounter++;
  186. }
  187.  
  188.  
  189.  
  190. static void select_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
  191. {
  192.    (void) pv;
  193.    gl_update_hitflag( ctx, ctx->VB->Win[v1][2] / DEPTH_SCALE );
  194.    gl_update_hitflag( ctx, ctx->VB->Win[v2][2] / DEPTH_SCALE );
  195. }
  196.  
  197.  
  198.  
  199. #if MAX_WIDTH > MAX_HEIGHT
  200. #  define MAXPOINTS MAX_WIDTH
  201. #else
  202. #  define MAXPOINTS MAX_HEIGHT
  203. #endif
  204.  
  205.  
  206. /* Flat, color index line */
  207. static void flat_ci_line( GLcontext *ctx,
  208.                           GLuint vert0, GLuint vert1, GLuint pvert )
  209. {
  210.    GLint count;
  211.    GLint *pbx = ctx->PB->x;
  212.    GLint *pby = ctx->PB->y;
  213.    PB_SET_INDEX( ctx, ctx->PB, ctx->VB->Index[pvert] );
  214.    count = ctx->PB->count;
  215.  
  216. #define INTERP_XY 1
  217.  
  218. #define PLOT(X,Y)        \
  219.     pbx[count] = X;        \
  220.     pby[count] = Y;        \
  221.     count++;
  222.  
  223. #include "linetemp.h"
  224.  
  225.    ctx->PB->count = count;
  226.    PB_CHECK_FLUSH( ctx, ctx->PB );
  227. }
  228.  
  229.  
  230.  
  231. /* Flat, color index line with Z interpolation/testing */
  232. static void flat_ci_z_line( GLcontext *ctx,
  233.                             GLuint vert0, GLuint vert1, GLuint pvert )
  234. {
  235.    GLint count;
  236.    GLint *pbx = ctx->PB->x;
  237.    GLint *pby = ctx->PB->y;
  238.    GLdepth *pbz = ctx->PB->z;
  239.    PB_SET_INDEX( ctx, ctx->PB, ctx->VB->Index[pvert] );
  240.    count = ctx->PB->count;
  241.  
  242. #define INTERP_XY 1
  243. #define INTERP_Z 1
  244.  
  245. #define PLOT(X,Y)        \
  246.     pbx[count] = X;        \
  247.     pby[count] = Y;        \
  248.     pbz[count] = Z;        \
  249.     count++;
  250.  
  251. #include "linetemp.h"
  252.  
  253.    ctx->PB->count = count;
  254.    PB_CHECK_FLUSH( ctx, ctx->PB );
  255. }
  256.  
  257.  
  258.  
  259. /* Flat-shaded, RGBA line */
  260. static void flat_rgba_line( GLcontext *ctx,
  261.                             GLuint vert0, GLuint vert1, GLuint pvert )
  262. {
  263.    GLint count;
  264.    GLint *pbx = ctx->PB->x;
  265.    GLint *pby = ctx->PB->y;
  266.    GLubyte *color = ctx->VB->Color[pvert];
  267.    PB_SET_COLOR( ctx, ctx->PB, color[0], color[1], color[2], color[3] );
  268.    count = ctx->PB->count;
  269.  
  270. #define INTERP_XY 1
  271.  
  272. #define PLOT(X,Y)        \
  273.     pbx[count] = X;        \
  274.     pby[count] = Y;        \
  275.     count++;
  276.  
  277. #include "linetemp.h"
  278.  
  279.    ctx->PB->count = count;
  280.    PB_CHECK_FLUSH( ctx, ctx->PB );
  281. }
  282.  
  283.  
  284.  
  285. /* Flat-shaded, RGBA line with Z interpolation/testing */
  286. static void flat_rgba_z_line( GLcontext *ctx,
  287.                               GLuint vert0, GLuint vert1, GLuint pvert )
  288. {
  289.    GLint count;
  290.    GLint *pbx = ctx->PB->x;
  291.    GLint *pby = ctx->PB->y;
  292.    GLdepth *pbz = ctx->PB->z;
  293.    GLubyte *color = ctx->VB->Color[pvert];
  294.    PB_SET_COLOR( ctx, ctx->PB, color[0], color[1], color[2], color[3] );
  295.    count = ctx->PB->count;
  296.  
  297. #define INTERP_XY 1
  298. #define INTERP_Z 1
  299.  
  300. #define PLOT(X,Y)    \
  301.     pbx[count] = X;    \
  302.     pby[count] = Y;    \
  303.     pbz[count] = Z;    \
  304.     count++;
  305.  
  306. #include "linetemp.h"
  307.  
  308.    ctx->PB->count = count;
  309.    PB_CHECK_FLUSH( ctx, ctx->PB );
  310. }
  311.  
  312.  
  313.  
  314. /* Smooth shaded, color index line */
  315. static void smooth_ci_line( GLcontext *ctx,
  316.                             GLuint vert0, GLuint vert1, GLuint pvert )
  317. {
  318.    GLint count = ctx->PB->count;
  319.    GLint *pbx = ctx->PB->x;
  320.    GLint *pby = ctx->PB->y;
  321.    GLuint *pbi = ctx->PB->i;
  322.    (void) pvert;
  323.  
  324. #define INTERP_XY 1
  325. #define INTERP_INDEX 1
  326.  
  327. #define PLOT(X,Y)        \
  328.     pbx[count] = X;        \
  329.     pby[count] = Y;        \
  330.     pbi[count] = I;        \
  331.     count++;
  332.  
  333. #include "linetemp.h"
  334.  
  335.    ctx->PB->count = count;
  336.    PB_CHECK_FLUSH( ctx, ctx->PB );
  337. }
  338.  
  339.  
  340.  
  341. /* Smooth shaded, color index line with Z interpolation/testing */
  342. static void smooth_ci_z_line( GLcontext *ctx,
  343.                               GLuint vert0, GLuint vert1, GLuint pvert )
  344. {
  345.    GLint count = ctx->PB->count;
  346.    GLint *pbx = ctx->PB->x;
  347.    GLint *pby = ctx->PB->y;
  348.    GLdepth *pbz = ctx->PB->z;
  349.    GLuint *pbi = ctx->PB->i;
  350.    (void) pvert;
  351.  
  352. #define INTERP_XY 1
  353. #define INTERP_Z 1
  354. #define INTERP_INDEX 1
  355.  
  356. #define PLOT(X,Y)        \
  357.     pbx[count] = X;        \
  358.     pby[count] = Y;        \
  359.     pbz[count] = Z;        \
  360.     pbi[count] = I;        \
  361.     count++;
  362.  
  363. #include "linetemp.h"
  364.  
  365.    ctx->PB->count = count;
  366.    PB_CHECK_FLUSH( ctx, ctx->PB );
  367. }
  368.  
  369.  
  370.  
  371. /* Smooth-shaded, RGBA line */
  372. static void smooth_rgba_line( GLcontext *ctx,
  373.                                  GLuint vert0, GLuint vert1, GLuint pvert )
  374. {
  375.    GLint count = ctx->PB->count;
  376.    GLint *pbx = ctx->PB->x;
  377.    GLint *pby = ctx->PB->y;
  378.    GLubyte (*pbrgba)[4] = ctx->PB->rgba;
  379.    (void) pvert;
  380.  
  381. #define INTERP_XY 1
  382. #define INTERP_RGB 1
  383. #define INTERP_ALPHA 1
  384.  
  385. #define PLOT(X,Y)            \
  386.     pbx[count] = X;            \
  387.     pby[count] = Y;            \
  388.     pbrgba[count][RCOMP] = FixedToInt(r0);    \
  389.     pbrgba[count][GCOMP] = FixedToInt(g0);    \
  390.     pbrgba[count][BCOMP] = FixedToInt(b0);    \
  391.     pbrgba[count][ACOMP] = FixedToInt(a0);    \
  392.     count++;
  393.  
  394. #include "linetemp.h"
  395.  
  396.    ctx->PB->count = count;
  397.    PB_CHECK_FLUSH( ctx, ctx->PB );
  398. }
  399.  
  400.  
  401.  
  402. /* Smooth-shaded, RGBA line with Z interpolation/testing */
  403. static void smooth_rgba_z_line( GLcontext *ctx,
  404.                                    GLuint vert0, GLuint vert1, GLuint pvert )
  405. {
  406.    GLint count = ctx->PB->count;
  407.    GLint *pbx = ctx->PB->x;
  408.    GLint *pby = ctx->PB->y;
  409.    GLdepth *pbz = ctx->PB->z;
  410.    GLubyte (*pbrgba)[4] = ctx->PB->rgba;
  411.    (void) pvert;
  412.  
  413. #define INTERP_XY 1
  414. #define INTERP_Z 1
  415. #define INTERP_RGB 1
  416. #define INTERP_ALPHA 1
  417.  
  418. #define PLOT(X,Y)            \
  419.     pbx[count] = X;            \
  420.     pby[count] = Y;            \
  421.     pbz[count] = Z;            \
  422.     pbrgba[count][RCOMP] = FixedToInt(r0);    \
  423.     pbrgba[count][GCOMP] = FixedToInt(g0);    \
  424.     pbrgba[count][BCOMP] = FixedToInt(b0);    \
  425.     pbrgba[count][ACOMP] = FixedToInt(a0);    \
  426.     count++;
  427.  
  428. #include "linetemp.h"
  429.  
  430.    ctx->PB->count = count;
  431.    PB_CHECK_FLUSH( ctx, ctx->PB );
  432. }
  433.  
  434.  
  435. #define CHECK_FULL(count)            \
  436.     if (count >= PB_SIZE-MAX_WIDTH) {    \
  437.        ctx->PB->count = count;        \
  438.        gl_flush_pb(ctx);            \
  439.        count = ctx->PB->count;        \
  440.     }
  441.  
  442.  
  443.  
  444. /* Smooth shaded, color index, any width, maybe stippled */
  445. static void general_smooth_ci_line( GLcontext *ctx,
  446.                                    GLuint vert0, GLuint vert1, GLuint pvert )
  447. {
  448.    GLint count = ctx->PB->count;
  449.    GLint *pbx = ctx->PB->x;
  450.    GLint *pby = ctx->PB->y;
  451.    GLdepth *pbz = ctx->PB->z;
  452.    GLuint *pbi = ctx->PB->i;
  453.    (void) pvert;
  454.  
  455.    if (ctx->Line.StippleFlag) {
  456.       /* stippled */
  457. #define INTERP_XY 1
  458. #define INTERP_Z 1
  459. #define INTERP_INDEX 1
  460. #define WIDE 1
  461. #define STIPPLE 1
  462. #define PLOT(X,Y)        \
  463.     pbx[count] = X;        \
  464.     pby[count] = Y;        \
  465.     pbz[count] = Z;        \
  466.     pbi[count] = I;        \
  467.     count++;        \
  468.     CHECK_FULL(count);
  469. #include "linetemp.h"
  470.    }
  471.    else {
  472.       /* unstippled */
  473.       if (ctx->Line.Width==2.0F) {
  474.          /* special case: unstippled and width=2 */
  475. #define INTERP_XY 1
  476. #define INTERP_Z 1
  477. #define INTERP_INDEX 1
  478. #define XMAJOR_PLOT(X,Y)            \
  479.     pbx[count] = X;  pbx[count+1] = X;    \
  480.     pby[count] = Y;  pby[count+1] = Y+1;    \
  481.     pbz[count] = Z;  pbz[count+1] = Z;    \
  482.     pbi[count] = I;  pbi[count+1] = I;    \
  483.     count += 2;                \
  484.     CHECK_FULL(count);
  485. #define YMAJOR_PLOT(X,Y)            \
  486.     pbx[count] = X;  pbx[count+1] = X+1;    \
  487.     pby[count] = Y;  pby[count+1] = Y;    \
  488.     pbz[count] = Z;  pbz[count+1] = Z;    \
  489.     pbi[count] = I;  pbi[count+1] = I;    \
  490.     count += 2;                \
  491.     CHECK_FULL(count);
  492. #include "linetemp.h"
  493.       }
  494.       else {
  495.          /* unstippled, any width */
  496. #define INTERP_XY 1
  497. #define INTERP_Z 1
  498. #define INTERP_INDEX 1
  499. #define WIDE 1
  500. #define PLOT(X,Y)        \
  501.     pbx[count] = X;        \
  502.     pby[count] = Y;        \
  503.     pbz[count] = Z;        \
  504.     pbi[count] = I;        \
  505.     count++;        \
  506.     CHECK_FULL(count);
  507. #include "linetemp.h"
  508.       }
  509.    }
  510.  
  511.    ctx->PB->count = count;
  512.    PB_CHECK_FLUSH( ctx, ctx->PB );
  513. }
  514.  
  515.  
  516. /* Flat shaded, color index, any width, maybe stippled */
  517. static void general_flat_ci_line( GLcontext *ctx,
  518.                                   GLuint vert0, GLuint vert1, GLuint pvert )
  519. {
  520.    GLint count;
  521.    GLint *pbx = ctx->PB->x;
  522.    GLint *pby = ctx->PB->y;
  523.    GLdepth *pbz = ctx->PB->z;
  524.    PB_SET_INDEX( ctx, ctx->PB, ctx->VB->Index[pvert] );
  525.    count = ctx->PB->count;
  526.  
  527.    if (ctx->Line.StippleFlag) {
  528.       /* stippled, any width */
  529. #define INTERP_XY 1
  530. #define INTERP_Z 1
  531. #define WIDE 1
  532. #define STIPPLE 1
  533. #define PLOT(X,Y)        \
  534.     pbx[count] = X;        \
  535.     pby[count] = Y;        \
  536.     pbz[count] = Z;        \
  537.     count++;        \
  538.     CHECK_FULL(count);
  539. #include "linetemp.h"
  540.    }
  541.    else {
  542.       /* unstippled */
  543.       if (ctx->Line.Width==2.0F) {
  544.          /* special case: unstippled and width=2 */
  545. #define INTERP_XY 1
  546. #define INTERP_Z 1
  547. #define XMAJOR_PLOT(X,Y)            \
  548.     pbx[count] = X;  pbx[count+1] = X;    \
  549.     pby[count] = Y;  pby[count+1] = Y+1;    \
  550.     pbz[count] = Z;  pbz[count+1] = Z;    \
  551.     count += 2;                \
  552.     CHECK_FULL(count);
  553. #define YMAJOR_PLOT(X,Y)            \
  554.     pbx[count] = X;  pbx[count+1] = X+1;    \
  555.     pby[count] = Y;  pby[count+1] = Y;    \
  556.     pbz[count] = Z;  pbz[count+1] = Z;    \
  557.     count += 2;                \
  558.     CHECK_FULL(count);
  559. #include "linetemp.h"
  560.       }
  561.       else {
  562.          /* unstippled, any width */
  563. #define INTERP_XY 1
  564. #define INTERP_Z 1
  565. #define WIDE 1
  566. #define PLOT(X,Y)        \
  567.     pbx[count] = X;        \
  568.     pby[count] = Y;        \
  569.     pbz[count] = Z;        \
  570.     count++;        \
  571.     CHECK_FULL(count);
  572. #include "linetemp.h"
  573.       }
  574.    }
  575.  
  576.    ctx->PB->count = count;
  577.    PB_CHECK_FLUSH( ctx, ctx->PB );
  578. }
  579.  
  580.  
  581.  
  582. static void general_smooth_rgba_line( GLcontext *ctx,
  583.                                       GLuint vert0, GLuint vert1, GLuint pvert)
  584. {
  585.    GLint count = ctx->PB->count;
  586.    GLint *pbx = ctx->PB->x;
  587.    GLint *pby = ctx->PB->y;
  588.    GLdepth *pbz = ctx->PB->z;
  589.    GLubyte (*pbrgba)[4] = ctx->PB->rgba;
  590.    (void) pvert;
  591.  
  592.    if (ctx->Line.StippleFlag) {
  593.       /* stippled */
  594. #define INTERP_XY 1
  595. #define INTERP_Z 1
  596. #define INTERP_RGB 1
  597. #define INTERP_ALPHA 1
  598. #define WIDE 1
  599. #define STIPPLE 1
  600. #define PLOT(X,Y)                \
  601.     pbx[count] = X;                \
  602.     pby[count] = Y;                \
  603.     pbz[count] = Z;                \
  604.     pbrgba[count][RCOMP] = FixedToInt(r0);    \
  605.     pbrgba[count][GCOMP] = FixedToInt(g0);    \
  606.     pbrgba[count][BCOMP] = FixedToInt(b0);    \
  607.     pbrgba[count][ACOMP] = FixedToInt(a0);    \
  608.     count++;                \
  609.     CHECK_FULL(count);
  610. #include "linetemp.h"
  611.    }
  612.    else {
  613.       /* unstippled */
  614.       if (ctx->Line.Width==2.0F) {
  615.          /* special case: unstippled and width=2 */
  616. #define INTERP_XY 1
  617. #define INTERP_Z 1
  618. #define INTERP_RGB 1
  619. #define INTERP_ALPHA 1
  620. #define XMAJOR_PLOT(X,Y)                \
  621.     pbx[count] = X;  pbx[count+1] = X;        \
  622.     pby[count] = Y;  pby[count+1] = Y+1;        \
  623.     pbz[count] = Z;  pbz[count+1] = Z;        \
  624.     pbrgba[count][RCOMP] = FixedToInt(r0);        \
  625.     pbrgba[count][GCOMP] = FixedToInt(g0);        \
  626.     pbrgba[count][BCOMP] = FixedToInt(b0);        \
  627.     pbrgba[count][ACOMP] = FixedToInt(a0);        \
  628.     pbrgba[count+1][RCOMP] = FixedToInt(r0);    \
  629.     pbrgba[count+1][GCOMP] = FixedToInt(g0);    \
  630.     pbrgba[count+1][BCOMP] = FixedToInt(b0);    \
  631.     pbrgba[count+1][ACOMP] = FixedToInt(a0);    \
  632.     count += 2;                    \
  633.     CHECK_FULL(count);
  634. #define YMAJOR_PLOT(X,Y)                \
  635.     pbx[count] = X;  pbx[count+1] = X+1;        \
  636.     pby[count] = Y;  pby[count+1] = Y;        \
  637.     pbz[count] = Z;  pbz[count+1] = Z;        \
  638.     pbrgba[count][RCOMP] = FixedToInt(r0);        \
  639.     pbrgba[count][GCOMP] = FixedToInt(g0);        \
  640.     pbrgba[count][BCOMP] = FixedToInt(b0);        \
  641.     pbrgba[count][ACOMP] = FixedToInt(a0);        \
  642.     pbrgba[count+1][RCOMP] = FixedToInt(r0);    \
  643.     pbrgba[count+1][GCOMP] = FixedToInt(g0);    \
  644.     pbrgba[count+1][BCOMP] = FixedToInt(b0);    \
  645.     pbrgba[count+1][ACOMP] = FixedToInt(a0);    \
  646.     count += 2;                    \
  647.     CHECK_FULL(count);
  648. #include "linetemp.h"
  649.       }
  650.       else {
  651.          /* unstippled, any width */
  652. #define INTERP_XY 1
  653. #define INTERP_Z 1
  654. #define INTERP_RGB 1
  655. #define INTERP_ALPHA 1
  656. #define WIDE 1
  657. #define PLOT(X,Y)                \
  658.     pbx[count] = X;                \
  659.     pby[count] = Y;                \
  660.     pbz[count] = Z;                \
  661.     pbrgba[count][RCOMP] = FixedToInt(r0);    \
  662.     pbrgba[count][GCOMP] = FixedToInt(g0);    \
  663.     pbrgba[count][BCOMP] = FixedToInt(b0);    \
  664.     pbrgba[count][ACOMP] = FixedToInt(a0);    \
  665.     count++;                \
  666.     CHECK_FULL(count);
  667. #include "linetemp.h"
  668.       }
  669.    }
  670.  
  671.    ctx->PB->count = count;
  672.    PB_CHECK_FLUSH( ctx, ctx->PB );
  673. }
  674.  
  675.  
  676. static void general_flat_rgba_line( GLcontext *ctx,
  677.                                     GLuint vert0, GLuint vert1, GLuint pvert )
  678. {
  679.    GLint count;
  680.    GLint *pbx = ctx->PB->x;
  681.    GLint *pby = ctx->PB->y;
  682.    GLdepth *pbz = ctx->PB->z;
  683.    GLubyte *color = ctx->VB->Color[pvert];
  684.    PB_SET_COLOR( ctx, ctx->PB, color[0], color[1], color[2], color[3] );
  685.    count = ctx->PB->count;
  686.  
  687.    if (ctx->Line.StippleFlag) {
  688.       /* stippled */
  689. #define INTERP_XY 1
  690. #define INTERP_Z 1
  691. #define WIDE 1
  692. #define STIPPLE 1
  693. #define PLOT(X,Y)            \
  694.     pbx[count] = X;            \
  695.     pby[count] = Y;            \
  696.     pbz[count] = Z;            \
  697.     count++;            \
  698.     CHECK_FULL(count);
  699. #include "linetemp.h"
  700.    }
  701.    else {
  702.       /* unstippled */
  703.       if (ctx->Line.Width==2.0F) {
  704.          /* special case: unstippled and width=2 */
  705. #define INTERP_XY 1
  706. #define INTERP_Z 1
  707. #define XMAJOR_PLOT(X,Y)            \
  708.     pbx[count] = X;  pbx[count+1] = X;    \
  709.     pby[count] = Y;  pby[count+1] = Y+1;    \
  710.     pbz[count] = Z;  pbz[count+1] = Z;    \
  711.     count += 2;                \
  712.     CHECK_FULL(count);
  713. #define YMAJOR_PLOT(X,Y)            \
  714.     pbx[count] = X;  pbx[count+1] = X+1;    \
  715.     pby[count] = Y;  pby[count+1] = Y;    \
  716.     pbz[count] = Z;  pbz[count+1] = Z;    \
  717.     count += 2;                \
  718.     CHECK_FULL(count);
  719. #include "linetemp.h"
  720.       }
  721.       else {
  722.          /* unstippled, any width */
  723. #define INTERP_XY 1
  724. #define INTERP_Z 1
  725. #define WIDE 1
  726. #define PLOT(X,Y)            \
  727.     pbx[count] = X;            \
  728.     pby[count] = Y;            \
  729.     pbz[count] = Z;            \
  730.     count++;            \
  731.     CHECK_FULL(count);
  732. #include "linetemp.h"
  733.       }
  734.    }
  735.  
  736.    ctx->PB->count = count;
  737.    PB_CHECK_FLUSH( ctx, ctx->PB );
  738. }
  739.  
  740.  
  741.  
  742. /* Flat-shaded, textured, any width, maybe stippled */
  743. static void flat_textured_line( GLcontext *ctx,
  744.                                 GLuint vert0, GLuint vert1, GLuint pv )
  745. {
  746.    GLint count;
  747.    GLint *pbx = ctx->PB->x;
  748.    GLint *pby = ctx->PB->y;
  749.    GLdepth *pbz = ctx->PB->z;
  750.    GLfloat *pbs = ctx->PB->s;
  751.    GLfloat *pbt = ctx->PB->t;
  752.    GLfloat *pbu = ctx->PB->u;
  753.    GLubyte *color = ctx->VB->Color[pv];
  754.    PB_SET_COLOR( ctx, ctx->PB, color[0], color[1], color[2], color[3] );
  755.    count = ctx->PB->count;
  756.  
  757.    if (ctx->Line.StippleFlag) {
  758.       /* stippled */
  759. #define INTERP_XY 1
  760. #define INTERP_Z 1
  761. #define INTERP_STUV 1
  762. #define WIDE 1
  763. #define STIPPLE 1
  764. #define PLOT(X,Y)            \
  765.     {                \
  766.        GLfloat invQ = 1.0F / hv0;    \
  767.        pbx[count] = X;        \
  768.        pby[count] = Y;        \
  769.        pbz[count] = Z;        \
  770.        pbs[count] = hs0 * invQ;    \
  771.        pbt[count] = ht0 * invQ;    \
  772.        pbu[count] = hu0 * invQ;    \
  773.        count++;            \
  774.        CHECK_FULL(count);        \
  775.     }
  776. #include "linetemp.h"
  777.    }
  778.    else {
  779.       /* unstippled */
  780. #define INTERP_XY 1
  781. #define INTERP_Z 1
  782. #define INTERP_STUV 1
  783. #define WIDE 1
  784. #define PLOT(X,Y)            \
  785.     {                \
  786.        GLfloat invQ = 1.0F / hv0;    \
  787.        pbx[count] = X;        \
  788.        pby[count] = Y;        \
  789.        pbz[count] = Z;        \
  790.        pbs[count] = hs0 * invQ;    \
  791.        pbt[count] = ht0 * invQ;    \
  792.        pbu[count] = hu0 * invQ;    \
  793.        count++;            \
  794.        CHECK_FULL(count);        \
  795.     }
  796. #include "linetemp.h"
  797.    }
  798.  
  799.    ctx->PB->count = count;
  800.    PB_CHECK_FLUSH( ctx, ctx->PB );
  801. }
  802.  
  803.  
  804.  
  805. /* Smooth-shaded, textured, any width, maybe stippled */
  806. static void smooth_textured_line( GLcontext *ctx,
  807.                                   GLuint vert0, GLuint vert1, GLuint pvert )
  808. {
  809.    GLint count = ctx->PB->count;
  810.    GLint *pbx = ctx->PB->x;
  811.    GLint *pby = ctx->PB->y;
  812.    GLdepth *pbz = ctx->PB->z;
  813.    GLfloat *pbs = ctx->PB->s;
  814.    GLfloat *pbt = ctx->PB->t;
  815.    GLfloat *pbu = ctx->PB->u;
  816.    GLubyte (*pbrgba)[4] = ctx->PB->rgba;
  817.    (void) pvert;
  818.  
  819.    if (ctx->Line.StippleFlag) {
  820.       /* stippled */
  821. #define INTERP_XY 1
  822. #define INTERP_Z 1
  823. #define INTERP_RGB 1
  824. #define INTERP_ALPHA 1
  825. #define INTERP_STUV 1
  826. #define WIDE 1
  827. #define STIPPLE 1
  828. #define PLOT(X,Y)                    \
  829.     {                        \
  830.        GLfloat invQ = 1.0F / hv0;            \
  831.        pbx[count] = X;                \
  832.        pby[count] = Y;                \
  833.        pbz[count] = Z;                \
  834.        pbs[count] = hs0 * invQ;            \
  835.        pbt[count] = ht0 * invQ;            \
  836.        pbu[count] = hu0 * invQ;            \
  837.        pbrgba[count][RCOMP] = FixedToInt(r0);    \
  838.        pbrgba[count][GCOMP] = FixedToInt(g0);    \
  839.        pbrgba[count][BCOMP] = FixedToInt(b0);    \
  840.        pbrgba[count][ACOMP] = FixedToInt(a0);    \
  841.        count++;                    \
  842.        CHECK_FULL(count);                \
  843.     }
  844. #include "linetemp.h"
  845.    }
  846.    else {
  847.       /* unstippled */
  848. #define INTERP_XY 1
  849. #define INTERP_Z 1
  850. #define INTERP_RGB 1
  851. #define INTERP_ALPHA 1
  852. #define INTERP_STUV 1
  853. #define WIDE 1
  854. #define PLOT(X,Y)                    \
  855.     {                        \
  856.        GLfloat invQ = 1.0F / hv0;            \
  857.        pbx[count] = X;                \
  858.        pby[count] = Y;                \
  859.        pbz[count] = Z;                \
  860.        pbs[count] = hs0 * invQ;            \
  861.        pbt[count] = ht0 * invQ;            \
  862.        pbu[count] = hu0 * invQ;            \
  863.        pbrgba[count][RCOMP] = FixedToInt(r0);    \
  864.        pbrgba[count][GCOMP] = FixedToInt(g0);    \
  865.        pbrgba[count][BCOMP] = FixedToInt(b0);    \
  866.        pbrgba[count][ACOMP] = FixedToInt(a0);    \
  867.        count++;                    \
  868.        CHECK_FULL(count);                \
  869.     }
  870. #include "linetemp.h"
  871.    }
  872.  
  873.    ctx->PB->count = count;
  874.    PB_CHECK_FLUSH( ctx, ctx->PB );
  875. }
  876.  
  877.  
  878.  
  879. /*
  880.  * Antialiased RGBA line
  881.  *
  882.  * This AA line function isn't terribly efficient but it's pretty
  883.  * straight-forward to understand.  Also, it doesn't exactly conform
  884.  * to the specification.
  885.  */
  886. static void aa_rgba_line( GLcontext *ctx,
  887.                           GLuint vert0, GLuint vert1, GLuint pvert )
  888. {
  889.    struct vertex_buffer *VB = ctx->VB;
  890.    struct pixel_buffer *pb = ctx->PB;
  891.    GLfloat halfWidth = 0.5F * ctx->Line.Width;  /* 0.5 is a bit of a hack */
  892.    GLboolean solid = !ctx->Line.StippleFlag;
  893.    GLint x0 = (GLint) VB->Win[vert0][0], x1 = (GLint) VB->Win[vert1][0];
  894.    GLint y0 = (GLint) VB->Win[vert0][1], y1 = (GLint) VB->Win[vert1][1];
  895.    GLint dx = x1 - x0;
  896.    GLint dy = y1 - y0;
  897.    GLint xStep, yStep;
  898.    GLint z0, z1;
  899.    GLfixed fr, fg, fb, fa;      /* fixed-pt RGBA */
  900.    GLfixed dfr, dfg, dfb, dfa;  /* fixed-pt RGBA deltas */
  901.  
  902.    if (dx == 0 && dy == 0)
  903.       return;
  904.  
  905. #if DEPTH_BITS==16
  906.    z0 = FloatToFixed(VB->Win[vert0][2]);
  907.    z1 = FloatToFixed(VB->Win[vert1][2]);
  908. #else
  909.    z0 = (int) VB->Win[vert0][2];
  910.    z1 = (int) VB->Win[vert1][2];
  911. #endif
  912.  
  913.    if (ctx->Light.ShadeModel == GL_SMOOTH) {
  914.       fr = IntToFixed(VB->Color[vert0][0]);
  915.       fg = IntToFixed(VB->Color[vert0][1]);
  916.       fb = IntToFixed(VB->Color[vert0][2]);
  917.       fa = IntToFixed(VB->Color[vert0][3]);
  918.    }
  919.    else {
  920.       fr = IntToFixed(VB->Color[pvert][0]);
  921.       fg = IntToFixed(VB->Color[pvert][1]);
  922.       fb = IntToFixed(VB->Color[pvert][2]);
  923.       fa = IntToFixed(VB->Color[pvert][3]);
  924.       dfr = dfg = dfb = dfa = 0;
  925.    }
  926.  
  927.    if (dx < 0) {
  928.       xStep = -1;
  929.       dx = -dx;
  930.    }
  931.    else {
  932.       xStep = 1;
  933.    }
  934.  
  935.    if (dy < 0) {
  936.       yStep = -1;
  937.       dy = -dy;
  938.    }
  939.    else {
  940.       yStep = 1;
  941.    }
  942.  
  943.    if (dx > dy) {
  944.       /* X-major line */
  945.       GLint i;
  946.       GLint x = x0;
  947.       GLfloat y = VB->Win[vert0][1];
  948.       GLfloat yStep = (VB->Win[vert1][1] - y) / (GLfloat) dx;
  949.       GLint dz = (z1 - z0) / dx;
  950.       if (ctx->Light.ShadeModel == GL_SMOOTH) {
  951.          dfr = (IntToFixed(VB->Color[vert1][0]) - fr) / dx;
  952.          dfg = (IntToFixed(VB->Color[vert1][1]) - fg) / dx;
  953.          dfb = (IntToFixed(VB->Color[vert1][2]) - fb) / dx;
  954.          dfa = (IntToFixed(VB->Color[vert1][3]) - fa) / dx;
  955.       }
  956.       for (i = 0; i < dx; i++) {
  957.          if (solid || (ctx->Line.StipplePattern & (1 << ((ctx->StippleCounter/ctx->Line.StippleFactor) & 0xf)))) {
  958.  
  959.             GLfloat yTop = y + halfWidth;
  960.             GLfloat yBot = y - halfWidth;
  961.             GLint yTopi = (GLint) yTop;
  962.             GLint yBoti = (GLint) yBot;
  963.             GLint iy;
  964.             GLint coverage;
  965.             GLubyte red   = FixedToInt(fr);
  966.             GLubyte green = FixedToInt(fg);
  967.             GLubyte blue  = FixedToInt(fb);
  968.             GLubyte alpha = FixedToInt(fa);
  969. #if DEPTH_BITS==16
  970.             GLdepth z = FixedToInt(z0);
  971. #else
  972.             GLdepth z = z0;
  973. #endif
  974.             ASSERT(yBoti < yTopi);
  975.  
  976.             {
  977.                /* bottom pixel of swipe */
  978.                coverage = (GLint) (alpha * (1.0F - (yBot - yBoti)));
  979.                PB_WRITE_RGBA_PIXEL( pb, x, yBoti, z, red, green, blue, coverage );
  980.                yBoti++;
  981.  
  982.                /* top pixel of swipe */
  983.                coverage = (GLint) (alpha * (yTop - yTopi));
  984.                PB_WRITE_RGBA_PIXEL( pb, x, yTopi, z, red, green, blue, coverage );
  985.                yTopi--;
  986.  
  987.                /* pixels between top and bottom with 100% coverage */
  988.                for (iy = yBoti; iy <= yTopi; iy++) {
  989.                   PB_WRITE_RGBA_PIXEL( pb, x, iy, z, red, green, blue, alpha );
  990.                }
  991.             }
  992.  
  993.             PB_CHECK_FLUSH( ctx, pb );
  994.  
  995.          } /* if stippling */
  996.  
  997.          x += xStep;
  998.          y += yStep;
  999.          z0 += dz;
  1000.          fr += dfr;
  1001.          fg += dfg;
  1002.          fb += dfb;
  1003.          fa += dfa;
  1004.          if (!solid)
  1005.             ctx->StippleCounter++;
  1006.       }
  1007.    }
  1008.    else {
  1009.       /* Y-major line */
  1010.       GLint i;
  1011.       GLint y = y0;
  1012.       GLfloat x = VB->Win[vert0][0];
  1013.       GLfloat xStep = (VB->Win[vert1][0] - x) / (GLfloat) dy;
  1014.       GLint dz = (z1 - z0) / dy;
  1015.       if (ctx->Light.ShadeModel == GL_SMOOTH) {
  1016.          dfr = (IntToFixed(VB->Color[vert1][0]) - fr) / dy;
  1017.          dfg = (IntToFixed(VB->Color[vert1][1]) - fg) / dy;
  1018.          dfb = (IntToFixed(VB->Color[vert1][2]) - fb) / dy;
  1019.          dfa = (IntToFixed(VB->Color[vert1][3]) - fa) / dy;
  1020.       }
  1021.       for (i = 0; i < dy; i++) {
  1022.          if (solid || (ctx->Line.StipplePattern & (1 << ((ctx->StippleCounter/ctx->Line.StippleFactor) & 0xf)))) {
  1023.             GLfloat xRight = x + halfWidth;
  1024.             GLfloat xLeft = x - halfWidth;
  1025.             GLint xRighti = (GLint) xRight;
  1026.             GLint xLefti = (GLint) xLeft;
  1027.             GLint ix;
  1028.             GLint coverage;
  1029.             GLubyte red   = FixedToInt(fr);
  1030.             GLubyte green = FixedToInt(fg);
  1031.             GLubyte blue  = FixedToInt(fb);
  1032.             GLubyte alpha = FixedToInt(fa);
  1033. #if DEPTH_BITS==16
  1034.             GLdepth z = FixedToInt(z0);
  1035. #else
  1036.             GLdepth z = z0;
  1037. #endif
  1038.  
  1039.             ASSERT(xLefti < xRight);
  1040.  
  1041.             {
  1042.                /* left pixel of swipe */
  1043.                coverage = (GLint) (alpha * (1.0F - (xLeft - xLefti)));
  1044.                PB_WRITE_RGBA_PIXEL( pb, xLefti, y, z, red, green, blue, coverage );
  1045.                xLefti++;
  1046.  
  1047.                /* right pixel of swipe */
  1048.                coverage = (GLint) (alpha * (xRight - xRighti));
  1049.                PB_WRITE_RGBA_PIXEL( pb, xRighti, y, z, red, green, blue, coverage );
  1050.                xRighti--;
  1051.  
  1052.                /* pixels between top and bottom with 100% coverage */
  1053.                for (ix = xLefti; ix <= xRighti; ix++) {
  1054.                   PB_WRITE_RGBA_PIXEL( pb, ix, y, z, red, green, blue, alpha );
  1055.                }
  1056.             }
  1057.  
  1058.             PB_CHECK_FLUSH( ctx, pb );
  1059.          }
  1060.  
  1061.          x += xStep;
  1062.          y += yStep;
  1063.          z0 += dz;
  1064.          fr += dfr;
  1065.          fg += dfg;
  1066.          fb += dfb;
  1067.          fa += dfa;
  1068.          if (!solid)
  1069.             ctx->StippleCounter++;
  1070.       }
  1071.    }
  1072. }
  1073.  
  1074.  
  1075. /*
  1076.  * Antialiased Textured RGBA line
  1077.  *
  1078.  * This AA line function isn't terribly efficient but it's pretty
  1079.  * straight-forward to understand.  Also, it doesn't exactly conform
  1080.  * to the specification.
  1081.  */
  1082. static void aa_tex_rgba_line( GLcontext *ctx,
  1083.                               GLuint vert0, GLuint vert1, GLuint pvert )
  1084. {
  1085.    struct vertex_buffer *VB = ctx->VB;
  1086.    struct pixel_buffer *pb = ctx->PB;
  1087.    GLfloat halfWidth = 0.5F * ctx->Line.Width;  /* 0.5 is a bit of a hack */
  1088.    GLboolean solid = !ctx->Line.StippleFlag;
  1089.    GLint x0 = (GLint) VB->Win[vert0][0], x1 = (GLint) VB->Win[vert1][0];
  1090.    GLint y0 = (GLint) VB->Win[vert0][1], y1 = (GLint) VB->Win[vert1][1];
  1091.    GLint dx = x1 - x0;
  1092.    GLint dy = y1 - y0;
  1093.    GLint xStep, yStep;
  1094.    GLint z0, z1;
  1095.    GLfixed fr, dfr;
  1096.    GLfixed fg, dfg;
  1097.    GLfixed fb, dfb;
  1098.    GLfixed fa, dfa;
  1099.    GLfloat hs0, dhs;     /* h denotes hyperbolic */
  1100.    GLfloat ht0, dht;
  1101.    GLfloat hu0, dhu;
  1102.    GLfloat hv0, dhv;
  1103.  
  1104.    if (dx == 0 && dy == 0)
  1105.       return;
  1106.  
  1107. #if DEPTH_BITS==16
  1108.    z0 = FloatToFixed(VB->Win[vert0][2]);
  1109.    z1 = FloatToFixed(VB->Win[vert1][2]);
  1110. #else
  1111.    z0 = (int) VB->Win[vert0][2];
  1112.    z1 = (int) VB->Win[vert1][2];
  1113. #endif
  1114.    {
  1115.       GLfloat invw0 = 1.0F / VB->Clip[vert0][3];
  1116.       GLfloat invw1 = 1.0F / VB->Clip[vert1][3];
  1117.       hs0 = VB->TexCoord[vert0][0] * invw0;
  1118.       dhs = VB->TexCoord[vert1][0] * invw1 - hs0;
  1119.       ht0 = VB->TexCoord[vert0][1] * invw0;
  1120.       dht = VB->TexCoord[vert1][1] * invw1 - ht0;
  1121.       hu0 = VB->TexCoord[vert0][2] * invw0;
  1122.       dhu = VB->TexCoord[vert1][2] * invw1 - hu0;
  1123.       hv0 = VB->TexCoord[vert0][3] * invw0;
  1124.       dhv = VB->TexCoord[vert1][3] * invw1 - hv0;
  1125.    }
  1126.  
  1127.    if (ctx->Light.ShadeModel == GL_SMOOTH) {
  1128.       fr = IntToFixed(VB->Color[vert0][0]);
  1129.       fg = IntToFixed(VB->Color[vert0][1]);
  1130.       fb = IntToFixed(VB->Color[vert0][2]);
  1131.       fa = IntToFixed(VB->Color[vert0][3]);
  1132.    }
  1133.    else {
  1134.       fr = IntToFixed(VB->Color[pvert][0]);
  1135.       fg = IntToFixed(VB->Color[pvert][1]);
  1136.       fb = IntToFixed(VB->Color[pvert][2]);
  1137.       fa = IntToFixed(VB->Color[pvert][3]);
  1138.       dfr = dfg = dfb = dfa = 0;
  1139.    }
  1140.  
  1141.    if (dx < 0) {
  1142.       xStep = -1;
  1143.       dx = -dx;
  1144.    }
  1145.    else {
  1146.       xStep = 1;
  1147.    }
  1148.  
  1149.    if (dy < 0) {
  1150.       yStep = -1;
  1151.       dy = -dy;
  1152.    }
  1153.    else {
  1154.       yStep = 1;
  1155.    }
  1156.  
  1157.    if (dx > dy) {
  1158.       /* X-major line */
  1159.       GLint i;
  1160.       GLint x = x0;
  1161.       GLfloat y = VB->Win[vert0][1];
  1162.       GLfloat yStep = (VB->Win[vert1][1] - y) / (GLfloat) dx;
  1163.       GLint dz = (z1 - z0) / dx;
  1164.       GLfloat invDx = 1.0F / dx;
  1165.       if (ctx->Light.ShadeModel == GL_SMOOTH) {
  1166.          dfr = (IntToFixed(VB->Color[vert1][0]) - fr) / dx;
  1167.          dfg = (IntToFixed(VB->Color[vert1][1]) - fg) / dx;
  1168.          dfb = (IntToFixed(VB->Color[vert1][2]) - fb) / dx;
  1169.          dfa = (IntToFixed(VB->Color[vert1][3]) - fa) / dx;
  1170.       }
  1171.       dhs *= invDx;
  1172.       dht *= invDx;
  1173.       dhu *= invDx;
  1174.       dhv *= invDx;
  1175.       for (i = 0; i < dx; i++) {
  1176.          if (solid || (ctx->Line.StipplePattern & (1 << ((ctx->StippleCounter/ctx->Line.StippleFactor) & 0xf)))) {
  1177.  
  1178.             GLfloat yTop = y + halfWidth;
  1179.             GLfloat yBot = y - halfWidth;
  1180.             GLint yTopi = (GLint) yTop;
  1181.             GLint yBoti = (GLint) yBot;
  1182.             GLint iy;
  1183.             GLint coverage;
  1184.             GLubyte red   = FixedToInt(fr);
  1185.             GLubyte green = FixedToInt(fg);
  1186.             GLubyte blue  = FixedToInt(fb);
  1187.             GLubyte alpha = FixedToInt(fa);
  1188. #if DEPTH_BITS==16
  1189.             GLdepth z = FixedToInt(z0);
  1190. #else
  1191.             GLdepth z = z0;
  1192. #endif
  1193.             ASSERT(yBoti <= yTopi);
  1194.  
  1195.             {
  1196.                GLfloat invQ = 1.0F / hv0;
  1197.                GLfloat s = hs0 * invQ;
  1198.                GLfloat t = ht0 * invQ;
  1199.                GLfloat u = hu0 * invQ;
  1200.  
  1201.                /* bottom pixel of swipe */
  1202.                coverage = (GLint) (alpha * (1.0F - (yBot - yBoti)));
  1203.                PB_WRITE_TEX_PIXEL( pb, x, yBoti, z, red, green, blue, coverage,
  1204.                                    s, t, u );
  1205.                yBoti++;
  1206.  
  1207.                /* top pixel of swipe */
  1208.                coverage = (GLint) (alpha * (yTop - yTopi));
  1209.                PB_WRITE_TEX_PIXEL( pb, x, yTopi, z, red, green, blue, coverage,
  1210.                                    s, t, u );
  1211.                yTopi--;
  1212.  
  1213.                /* pixels between top and bottom with 100% coverage */
  1214.                for (iy = yBoti; iy <= yTopi; iy++) {
  1215.                   PB_WRITE_TEX_PIXEL( pb, x, iy, z, red, green, blue, alpha,
  1216.                                       s, t, u );
  1217.                }
  1218.             }
  1219.             PB_CHECK_FLUSH( ctx, pb );
  1220.  
  1221.          } /* if stippling */
  1222.  
  1223.          x += xStep;
  1224.          y += yStep;
  1225.          z0 += dz;
  1226.          fr += dfr;
  1227.          fg += dfg;
  1228.          fb += dfb;
  1229.          fa += dfa;
  1230.          hs0 += dhs;
  1231.          ht0 += dht;
  1232.          hu0 += dhu;
  1233.          hv0 += dhv;
  1234.  
  1235.          if (!solid)
  1236.             ctx->StippleCounter++;
  1237.       }
  1238.    }
  1239.    else {
  1240.       /* Y-major line */
  1241.       GLint i;
  1242.       GLint y = y0;
  1243.       GLfloat x = VB->Win[vert0][0];
  1244.       GLfloat xStep = (VB->Win[vert1][0] - x) / (GLfloat) dy;
  1245.       GLint dz = (z1 - z0) / dy;
  1246.       GLfloat invDy = 1.0F / dy;
  1247.       if (ctx->Light.ShadeModel == GL_SMOOTH) {
  1248.          dfr = (IntToFixed(VB->Color[vert1][0]) - fr) / dy;
  1249.          dfg = (IntToFixed(VB->Color[vert1][1]) - fg) / dy;
  1250.          dfb = (IntToFixed(VB->Color[vert1][2]) - fb) / dy;
  1251.          dfa = (IntToFixed(VB->Color[vert1][3]) - fa) / dy;
  1252.       }
  1253.       dhs *= invDy;
  1254.       dht *= invDy;
  1255.       dhu *= invDy;
  1256.       dhv *= invDy;
  1257.       for (i = 0; i < dy; i++) {
  1258.          if (solid || (ctx->Line.StipplePattern & (1 << ((ctx->StippleCounter/ctx->Line.StippleFactor) & 0xf)))) {
  1259.             GLfloat xRight = x + halfWidth;
  1260.             GLfloat xLeft = x - halfWidth;
  1261.             GLint xRighti = (GLint) xRight;
  1262.             GLint xLefti = (GLint) xLeft;
  1263.             GLint ix;
  1264.             GLint coverage;
  1265.             GLubyte red   = FixedToInt(fr);
  1266.             GLubyte green = FixedToInt(fg);
  1267.             GLubyte blue  = FixedToInt(fb);
  1268.             GLubyte alpha = FixedToInt(fa);
  1269. #if DEPTH_BITS==16
  1270.             GLdepth z = FixedToInt(z0);
  1271. #else
  1272.             GLdepth z = z0;
  1273. #endif
  1274.  
  1275.             ASSERT(xLefti < xRight);
  1276.  
  1277.             {
  1278.                GLfloat invQ = 1.0F / hv0;
  1279.                GLfloat s = hs0 * invQ;
  1280.                GLfloat t = ht0 * invQ;
  1281.                GLfloat u = hu0 * invQ;
  1282.  
  1283.                /* left pixel of swipe */
  1284.                coverage = (GLint) (alpha * (1.0F - (xLeft - xLefti)));
  1285.                PB_WRITE_TEX_PIXEL( pb, xLefti, y, z, red, green, blue, coverage,
  1286.                                    s, t, u );
  1287.                xLefti++;
  1288.  
  1289.                /* right pixel of swipe */
  1290.                coverage = (GLint) (alpha * (xRight - xRighti));
  1291.                PB_WRITE_TEX_PIXEL( pb, xRighti, y, z, red, green, blue, coverage,
  1292.                                    s, t, u );
  1293.                xRighti--;
  1294.  
  1295.                /* pixels between top and bottom with 100% coverage */
  1296.                for (ix = xLefti; ix <= xRighti; ix++) {
  1297.                   PB_WRITE_TEX_PIXEL( pb, ix, y, z, red, green, blue, alpha,
  1298.                                       s, t, u );
  1299.                }
  1300.             }
  1301.             PB_CHECK_FLUSH( ctx, pb );
  1302.          }
  1303.  
  1304.          x += xStep;
  1305.          y += yStep;
  1306.          z0 += dz;
  1307.          fr += dfr;
  1308.          fg += dfg;
  1309.          fb += dfb;
  1310.          fa += dfa;
  1311.          hs0 += dhs;
  1312.          ht0 += dht;
  1313.          hu0 += dhu;
  1314.          hv0 += dhv;
  1315.          if (!solid)
  1316.             ctx->StippleCounter++;
  1317.       }
  1318.    }
  1319. }
  1320.  
  1321.  
  1322.  
  1323.  
  1324. /*
  1325.  * Antialiased CI line.  Same comments for RGBA antialiased lines apply.
  1326.  */
  1327. static void aa_ci_line( GLcontext *ctx,
  1328.                         GLuint vert0, GLuint vert1, GLuint pvert )
  1329. {
  1330.    struct vertex_buffer *VB = ctx->VB;
  1331.    struct pixel_buffer *pb = ctx->PB;
  1332.    GLfloat halfWidth = 0.5F * ctx->Line.Width;  /* 0.5 is a bit of a hack */
  1333.    GLboolean solid = !ctx->Line.StippleFlag;
  1334.    GLint x0 = (GLint) VB->Win[vert0][0], x1 = (GLint) VB->Win[vert1][0];
  1335.    GLint y0 = (GLint) VB->Win[vert0][1], y1 = (GLint) VB->Win[vert1][1];
  1336.    GLint dx = x1 - x0;
  1337.    GLint dy = y1 - y0;
  1338.    GLint xStep, yStep;
  1339.    GLint z0, z1;
  1340.    GLfixed fi, dfi;
  1341.  
  1342.    if (dx == 0 && dy == 0)
  1343.       return;
  1344.  
  1345. #if DEPTH_BITS==16
  1346.    z0 = FloatToFixed(VB->Win[vert0][2]);
  1347.    z1 = FloatToFixed(VB->Win[vert1][2]);
  1348. #else
  1349.    z0 = (int) VB->Win[vert0][2];
  1350.    z1 = (int) VB->Win[vert1][2];
  1351. #endif
  1352.  
  1353.    if (ctx->Light.ShadeModel == GL_SMOOTH) {
  1354.       fi = IntToFixed(VB->Index[vert0]);
  1355.    }
  1356.    else {
  1357.       fi = IntToFixed(VB->Index[pvert]);
  1358.       dfi = 0;
  1359.    }
  1360.  
  1361.    if (dx < 0) {
  1362.       xStep = -1;
  1363.       dx = -dx;
  1364.    }
  1365.    else {
  1366.       xStep = 1;
  1367.    }
  1368.  
  1369.    if (dy < 0) {
  1370.       yStep = -1;
  1371.       dy = -dy;
  1372.    }
  1373.    else {
  1374.       yStep = 1;
  1375.    }
  1376.  
  1377.    if (dx > dy) {
  1378.       /* X-major line */
  1379.       GLint i;
  1380.       GLint x = x0;
  1381.       GLfloat y = VB->Win[vert0][1];
  1382.       GLfloat yStep = (VB->Win[vert1][1] - y) / (GLfloat) dx;
  1383.       GLint dz = (z1 - z0) / dx;
  1384.       if (ctx->Light.ShadeModel == GL_SMOOTH) {
  1385.          dfi = (IntToFixed(VB->Index[vert1]) - fi) / dx;
  1386.       }
  1387.       for (i = 0; i < dx; i++) {
  1388.          if (solid || (ctx->Line.StipplePattern & (1 << ((ctx->StippleCounter/ctx->Line.StippleFactor) & 0xf)))) {
  1389.  
  1390.             GLfloat yTop = y + halfWidth;
  1391.             GLfloat yBot = y - halfWidth;
  1392.             GLint yTopi = (GLint) yTop;
  1393.             GLint yBoti = (GLint) yBot;
  1394.             GLint iy;
  1395.             GLuint coverage;
  1396.             GLuint index = FixedToInt(fi) & 0xfffffff0;
  1397. #if DEPTH_BITS==16
  1398.             GLdepth z = FixedToInt(z0);
  1399. #else
  1400.             GLdepth z = z0;
  1401. #endif
  1402.  
  1403.             ASSERT(yBoti <= yTopi);
  1404.  
  1405.             /* bottom pixel of swipe */
  1406.             coverage = (GLuint) (15.0F * (1.0F - (yBot - yBoti)));
  1407.             PB_WRITE_CI_PIXEL( pb, x, yBoti, z, index + coverage );
  1408.             yBoti++;
  1409.  
  1410.             /* top pixel of swipe */
  1411.             coverage = (GLuint) (15.0F * (yTop - yTopi));
  1412.             PB_WRITE_CI_PIXEL( pb, x, yTopi, z, index + coverage );
  1413.             yTopi--;
  1414.  
  1415.             /* pixels between top and bottom with 100% coverage */
  1416.             for (iy = yBoti; iy <= yTopi; iy++) {
  1417.                PB_WRITE_CI_PIXEL( pb, x, iy, z, index + 15 );
  1418.             }
  1419.          }
  1420.  
  1421.          PB_CHECK_FLUSH( ctx, pb );
  1422.  
  1423.          x += xStep;
  1424.          y += yStep;
  1425.          z0 += dz;
  1426.          fi += dfi;
  1427.          if (!solid)
  1428.             ctx->StippleCounter++;
  1429.       }
  1430.    }
  1431.    else {
  1432.       /* Y-major line */
  1433.       GLint i;
  1434.       GLint y = y0;
  1435.       GLfloat x = VB->Win[vert0][0];
  1436.       GLfloat xStep = (VB->Win[vert1][0] - x) / (GLfloat) dy;
  1437.       GLint dz = (z1 - z0) / dy;
  1438.       if (ctx->Light.ShadeModel == GL_SMOOTH) {
  1439.          dfi = (IntToFixed(VB->Index[vert1]) - fi) / dy;
  1440.       }
  1441.       for (i = 0; i < dy; i++) {
  1442.          if (solid || (ctx->Line.StipplePattern & (1 << ((ctx->StippleCounter/ctx->Line.StippleFactor) & 0xf)))) {
  1443.             GLfloat xRight = x + halfWidth;
  1444.             GLfloat xLeft = x - halfWidth;
  1445.             GLint xRighti = (GLint) xRight;
  1446.             GLint xLefti = (GLint) xLeft;
  1447.             GLint ix;
  1448.             GLuint coverage;
  1449.             GLuint index = FixedToInt(fi) & 0xfffffff0;
  1450. #if DEPTH_BITS==16
  1451.             GLdepth z = FixedToInt(z0);
  1452. #else
  1453.             GLdepth z = z0;
  1454. #endif
  1455.  
  1456.             ASSERT(xLefti < xRight);
  1457.  
  1458.             /* left pixel of swipe */
  1459.             coverage = (GLuint) (15.0F * (1.0F - (xLeft - xLefti)));
  1460.             PB_WRITE_CI_PIXEL( pb, xLefti, y, z, index + coverage );
  1461.             xLefti++;
  1462.  
  1463.             /* right pixel of swipe */
  1464.             coverage = (GLuint) (15.0F * (xRight - xRighti));
  1465.             PB_WRITE_CI_PIXEL( pb, xRighti, y, z, index + coverage );
  1466.             xRighti--;
  1467.  
  1468.             /* pixels between top and bottom with 100% coverage */
  1469.             for (ix = xLefti; ix <= xRighti; ix++) {
  1470.                PB_WRITE_CI_PIXEL( pb, ix, y, z, index + 15 );
  1471.             }
  1472.          }
  1473.  
  1474.          PB_CHECK_FLUSH( ctx, pb );
  1475.  
  1476.          x += xStep;
  1477.          y += yStep;
  1478.          z0 += dz;
  1479.          fi += dfi;
  1480.          if (!solid)
  1481.             ctx->StippleCounter++;
  1482.  
  1483.       }
  1484.    }
  1485. }
  1486.  
  1487.  
  1488.  
  1489.  
  1490. /*
  1491.  * Null rasterizer for measuring transformation speed.
  1492.  */
  1493. static void null_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
  1494. {
  1495.    (void) ctx;
  1496.    (void) v1;
  1497.    (void) v2;
  1498.    (void) pv;
  1499. }
  1500.  
  1501.  
  1502.  
  1503. /*
  1504.  * Determine which line drawing function to use given the current
  1505.  * rendering context.
  1506.  */
  1507. void gl_set_line_function( GLcontext *ctx )
  1508. {
  1509.    GLboolean rgbmode = ctx->Visual->RGBAflag;
  1510.    /* TODO: antialiased lines */
  1511.  
  1512.    if (ctx->RenderMode==GL_RENDER) {
  1513.       if (ctx->NoRaster) {
  1514.          ctx->Driver.LineFunc = null_line;
  1515.          return;
  1516.       }
  1517.       if (ctx->Driver.LineFunc) {
  1518.          /* Device driver will draw lines. */
  1519.          ctx->Driver.LineFunc = ctx->Driver.LineFunc;
  1520.       }
  1521.       else if (ctx->Line.SmoothFlag) {
  1522.          /* antialiased lines */
  1523.          if (rgbmode) {
  1524.             if (ctx->Texture.Enabled)
  1525.                ctx->Driver.LineFunc = aa_tex_rgba_line;
  1526.             else
  1527.                ctx->Driver.LineFunc = aa_rgba_line;
  1528.          }
  1529.          else {
  1530.             ctx->Driver.LineFunc = aa_ci_line;
  1531.          }
  1532.       }
  1533.       else if (ctx->Texture.Enabled) {
  1534.          if (ctx->Light.ShadeModel==GL_SMOOTH) {
  1535.             ctx->Driver.LineFunc = smooth_textured_line;
  1536.          }
  1537.          else {
  1538.             ctx->Driver.LineFunc = flat_textured_line;
  1539.          }
  1540.       }
  1541.       else if (ctx->Line.Width!=1.0 || ctx->Line.StippleFlag
  1542.                || ctx->Line.SmoothFlag || ctx->Texture.Enabled) {
  1543.          if (ctx->Light.ShadeModel==GL_SMOOTH) {
  1544.             if (rgbmode)
  1545.                ctx->Driver.LineFunc = general_smooth_rgba_line;
  1546.             else
  1547.                ctx->Driver.LineFunc = general_smooth_ci_line;
  1548.          }
  1549.          else {
  1550.             if (rgbmode)
  1551.                ctx->Driver.LineFunc = general_flat_rgba_line;
  1552.             else
  1553.                ctx->Driver.LineFunc = general_flat_ci_line;
  1554.          }
  1555.       }
  1556.       else {
  1557.      if (ctx->Light.ShadeModel==GL_SMOOTH) {
  1558.         /* Width==1, non-stippled, smooth-shaded */
  1559.             if (ctx->Depth.Test
  1560.             || (ctx->Fog.Enabled && ctx->Hint.Fog==GL_NICEST)) {
  1561.                if (rgbmode)
  1562.                   ctx->Driver.LineFunc = smooth_rgba_z_line;
  1563.                else
  1564.                   ctx->Driver.LineFunc = smooth_ci_z_line;
  1565.             }
  1566.             else {
  1567.                if (rgbmode)
  1568.                   ctx->Driver.LineFunc = smooth_rgba_line;
  1569.                else
  1570.                   ctx->Driver.LineFunc = smooth_ci_line;
  1571.             }
  1572.      }
  1573.          else {
  1574.         /* Width==1, non-stippled, flat-shaded */
  1575.             if (ctx->Depth.Test
  1576.                 || (ctx->Fog.Enabled && ctx->Hint.Fog==GL_NICEST)) {
  1577.                if (rgbmode)
  1578.                   ctx->Driver.LineFunc = flat_rgba_z_line;
  1579.                else
  1580.                   ctx->Driver.LineFunc = flat_ci_z_line;
  1581.             }
  1582.             else {
  1583.                if (rgbmode)
  1584.                   ctx->Driver.LineFunc = flat_rgba_line;
  1585.                else
  1586.                   ctx->Driver.LineFunc = flat_ci_line;
  1587.             }
  1588.          }
  1589.       }
  1590.    }
  1591.    else if (ctx->RenderMode==GL_FEEDBACK) {
  1592.       ctx->Driver.LineFunc = feedback_line;
  1593.    }
  1594.    else {
  1595.       /* GL_SELECT mode */
  1596.       ctx->Driver.LineFunc = select_line;
  1597.    }
  1598. }
  1599.  
  1600.